home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / dev / src / stefanb_src.lha / Old_Projects / ToolManager / Source / library / execobj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-09  |  25.5 KB  |  872 lines

  1. /*
  2.  * execobj.c  V2.1.01
  3.  *
  4.  * TMObject, Type: Exec
  5.  *
  6.  * (c) 1990-1996 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* extended TMObject structure for TMOBJTYPE_Exec objects */
  12. struct TMObjectExec {
  13.                      struct TMObject    eo_Object;
  14.                      UWORD              eo_Type;
  15.                      UWORD              eo_Flags;
  16.                      char              *eo_Command;
  17.                      char              *eo_CurrentDir;
  18.                      LONG               eo_Delay;
  19.                      char              *eo_HotKey;
  20.                      char              *eo_Output;
  21.                      char              *eo_Path;
  22.                      LONG               eo_Priority;
  23.                      char              *eo_PubScreen;
  24.                      LONG               eo_Stack;
  25.                      CxObj             *eo_CxObj;
  26.                      struct TMHandle   *eo_Handle;
  27.                      void              *eo_LinkData;
  28.                      struct TMLink      eo_Link;
  29.                      struct TMTimerReq  eo_TimerReq;
  30.                     };
  31.  
  32. /* eo_Flags */
  33. #define EO_Arguments (1L<<0)
  34. #define EO_ToFront   (1L<<1)
  35.  
  36. /* Tag to Flag mapping table for PackBoolTags */
  37. static struct TagItem flagmap[]={TMOP_Arguments, EO_Arguments,
  38.                                  TMOP_ToFront,   EO_ToFront,
  39.                                  TAG_DONE};
  40.  
  41. /* Structure for path list */
  42. struct PathList {
  43.                  BPTR NextPath; /* Pointer to next PathList */
  44.                  BPTR PathLock; /* Lock on directory */
  45.                 };
  46.  
  47. /* Global data */
  48. struct Library *WBStartBase;
  49.  
  50. /* Create an Exec object */
  51. struct TMObject *CreateTMObjectExec(struct TMHandle *handle, char *name,
  52.                                     struct TagItem *tags)
  53. {
  54.  struct TMObjectExec *tmobj;
  55.  
  56.  /* allocate memory for object */
  57.  if (tmobj=(struct TMObjectExec *)
  58.             AllocateTMObject(sizeof(struct TMObjectExec))) {
  59.   struct TagItem *ti,*tstate;
  60.   BOOL noerror=TRUE;
  61.  
  62.   /* Set object defaults */
  63.   tmobj->eo_Type=TMET_CLI;
  64.   tmobj->eo_Command=DefaultNoName;
  65.   tmobj->eo_CurrentDir=DefaultDirName;
  66.   tmobj->eo_Output=DefaultOutput;
  67.   tmobj->eo_Stack=4096;
  68.   tmobj->eo_Handle=handle;
  69.  
  70.   /* Scan tag list */
  71.   tstate=tags;
  72.   while (noerror && (ti=NextTagItem(&tstate))) {
  73.  
  74.    DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  75.  
  76.    switch (ti->ti_Tag) {
  77.     case TMOP_Command:    {
  78.                            char *s=(char *) ti->ti_Data;
  79.                            if (s) tmobj->eo_Command=s;
  80.                           }
  81.                           break;
  82.     case TMOP_CurrentDir: {
  83.                            char *s=(char *) ti->ti_Data;
  84.                            if (s) tmobj->eo_CurrentDir=s;
  85.                           }
  86.                           break;
  87.     case TMOP_Delay:      tmobj->eo_Delay=ti->ti_Data;
  88.                           break;
  89.     case TMOP_ExecType:   {
  90.                            UWORD type=ti->ti_Data;
  91.  
  92.                            /* Sanity check */
  93.                            if ((type <= TMET_Network) || (type == TMET_Hook))
  94.                             tmobj->eo_Type=type;
  95.                            else
  96.                             noerror=FALSE;
  97.                           }
  98.                           break;
  99.     case TMOP_HotKey:     tmobj->eo_HotKey=(char *) ti->ti_Data;
  100.                           break;
  101.     case TMOP_Output:     {
  102.                            char *s=(char *) ti->ti_Data;
  103.                            if (s) tmobj->eo_Output=s;
  104.                           }
  105.                           break;
  106.     case TMOP_Path:       tmobj->eo_Path=(char *) ti->ti_Data;
  107.                           break;
  108.     case TMOP_Priority:   tmobj->eo_Priority=ti->ti_Data;
  109.                           break;
  110.     case TMOP_PubScreen:  tmobj->eo_PubScreen=(char *) ti->ti_Data;
  111.                           break;
  112.     case TMOP_Stack:      tmobj->eo_Stack=ti->ti_Data;
  113.                           break;
  114.    }
  115.   }
  116.  
  117.   /* No errors? */
  118.   if (noerror) {
  119.    BOOL hotkey=tmobj->eo_HotKey!=NULL;
  120.  
  121.    /* HotKey set? Create Commodities object from HotKey description */
  122.    if  (hotkey && (tmobj->eo_CxObj=HotKey(tmobj->eo_HotKey,BrokerPort,
  123.                                           (ULONG) &tmobj->eo_Link))) {
  124.  
  125.     DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->eo_CxObj);
  126.  
  127.     /* Attach object to broker */
  128.     AttachCxObj(Broker,tmobj->eo_CxObj);
  129.    }
  130.  
  131.    /* No HotKey or no HotKey error? */
  132.    if (!hotkey || (tmobj->eo_CxObj && !CxObjError(Broker))) {
  133.     /* No. Set flags */
  134.     tmobj->eo_Flags=PackBoolTags(EO_Arguments,tags,flagmap);
  135.  
  136.     /* Initialize rest of structure */
  137.     tmobj->eo_Link.tml_Linked=(struct TMObject *) tmobj;
  138.     tmobj->eo_Link.tml_Active=FALSE;
  139.     tmobj->eo_TimerReq.tmtr_Request=*deftimereq;
  140.     tmobj->eo_TimerReq.tmtr_Link=&tmobj->eo_Link;
  141.  
  142.     /* All OK */
  143.     return(tmobj);
  144.    }
  145.  
  146.    /* Free resources */
  147.    if (tmobj->eo_CxObj) SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  148.   }
  149.   FreeMem(tmobj,sizeof(struct TMObjectExec));
  150.  }
  151.  
  152.  /* call failed */
  153.  return(NULL);
  154. }
  155.  
  156. /* Delete an Exec object */
  157. BOOL DeleteTMObjectExec(struct TMObjectExec *tmobj)
  158. {
  159.  DEBUG_PRINTF("Delete/Exec (0x%08lx)\n",tmobj);
  160.  
  161.  /* timer request active? */
  162.  if (tmobj->eo_Link.tml_Active) {
  163.   struct IORequest *tr=(struct IORequest *) &tmobj->eo_TimerReq;
  164.  
  165.   /* If timer request still active, abort it */
  166.   if (!CheckIO(tr)) AbortIO(tr);
  167.  
  168.   /* Remove timer request */
  169.   WaitIO(tr);
  170.   tmobj->eo_Link.tml_Active=FALSE;
  171.  }
  172.  
  173.  /* Free internal data */
  174.  if (tmobj->eo_LinkData)
  175.   switch(tmobj->eo_Type) {
  176.    case TMET_HotKey: FreeMem(tmobj->eo_LinkData,sizeof(struct InputEvent));
  177.                      break;
  178.    case TMET_Dock:   RemLinkTMObject(tmobj->eo_LinkData);
  179.                      break;
  180.   }
  181.  
  182.  /* Remove links */
  183.  DeleteAllLinksTMObject((struct TMObject *) tmobj);
  184.  
  185.  /* Free resources */
  186.  if (tmobj->eo_CxObj) SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  187.  
  188.  /* Remove object from list */
  189.  Remove((struct Node *) tmobj);
  190.  
  191.  /* Free object */
  192.  FreeMem(tmobj,sizeof(struct TMObjectExec));
  193.  
  194.  /* All OK. */
  195.  return(TRUE);
  196. }
  197.  
  198. /* Change an Exec object */
  199. struct TMObject *ChangeTMObjectExec(struct TMHandle *handle,
  200.                                     struct TMObjectExec *tmobj,
  201.                                     struct TagItem *tags)
  202. {
  203.  struct TagItem *ti,*tstate;
  204.  
  205.  /* Scan tag list */
  206.  tstate=tags;
  207.  while (ti=NextTagItem(&tstate)) {
  208.  
  209.   DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  210.  
  211.   switch (ti->ti_Tag) {
  212.    case TMOP_Command:    {
  213.                           char *s=(char *) ti->ti_Data;
  214.                           if (s) tmobj->eo_Command=s;
  215.                          }
  216.                          break;
  217.    case TMOP_CurrentDir: {
  218.                           char *s=(char *) ti->ti_Data;
  219.                           if (s) tmobj->eo_CurrentDir=s;
  220.                          }
  221.                          break;
  222.    case TMOP_Delay:      tmobj->eo_Delay=ti->ti_Data;
  223.                          break;
  224.    case TMOP_ExecType:   {
  225.                           UWORD type=ti->ti_Data;
  226.  
  227.                           /* Sanity check */
  228.                           if ((type <= TMET_Network) || (type == TMET_Hook))
  229.                            tmobj->eo_Type=type;
  230.                          }
  231.                          break;
  232.    case TMOP_HotKey:     if (tmobj->eo_CxObj) {
  233.                           SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  234.                           tmobj->eo_CxObj=NULL;
  235.                          }
  236.  
  237.                          tmobj->eo_HotKey=(char *) ti->ti_Data;
  238.                          break;
  239.    case TMOP_Output:     {
  240.                           char *s=(char *) ti->ti_Data;
  241.                           if (s) tmobj->eo_Output=s;
  242.                          }
  243.                          break;
  244.    case TMOP_Path:       tmobj->eo_Path=(char *) ti->ti_Data;
  245.                          break;
  246.    case TMOP_Priority:   tmobj->eo_Priority=ti->ti_Data;
  247.                          break;
  248.    case TMOP_PubScreen:  tmobj->eo_PubScreen=(char *) ti->ti_Data;
  249.                          break;
  250.    case TMOP_Stack:      tmobj->eo_Stack=ti->ti_Data;
  251.                          break;
  252.   }
  253.  }
  254.  
  255.  /* HotKey set? Create Commodities object from HotKey description */
  256.  if  (tmobj->eo_HotKey && !tmobj->eo_CxObj &&
  257.       (tmobj->eo_CxObj=HotKey(tmobj->eo_HotKey,BrokerPort,
  258.                               (ULONG) &tmobj->eo_Link))) {
  259.  
  260.   DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->eo_CxObj);
  261.  
  262.   /* Attach object to broker */
  263.   AttachCxObj(Broker,tmobj->eo_CxObj);
  264.  
  265.   /* Commodities error? */
  266.   if (CxObjError(Broker)) {
  267.    SafeDeleteCxObjAll(tmobj->eo_CxObj,&tmobj->eo_Link);
  268.    tmobj->eo_CxObj=NULL;
  269.   }
  270.  }
  271.  
  272.  /* Set flags */
  273.  tmobj->eo_Flags=PackBoolTags(tmobj->eo_Flags,tags,flagmap);
  274.  
  275.  /* All OK */
  276.  return(TRUE);
  277. }
  278.  
  279. /* Allocate & Initialize a TMLink structure */
  280. struct TMLink *AllocLinkTMObjectExec(struct TMObjectExec *tmobj)
  281. {
  282.  struct TMLink *tml;
  283.  
  284.  /* Allocate memory for link structure */
  285.  if (tml=AllocMem(sizeof(struct TMLink),MEMF_CLEAR|MEMF_PUBLIC))
  286.   /* Initialize link structure */
  287.   tml->tml_Size=sizeof(struct TMLink);
  288.  
  289.  return(tml);
  290. }
  291.  
  292. /* Clear link to Dock object */
  293. void DeleteLinkTMObjectExec(struct TMLink *tml)
  294. {
  295.  struct TMObjectExec *tmobj=(struct TMObjectExec *) tml->tml_LinkedTo;
  296.  
  297.  tmobj->eo_LinkData=NULL;
  298. }
  299.  
  300. /* Copy a path list */
  301. BOOL CopyPathList(struct PathList **pla, struct PathList **plc,
  302.                   struct PathList *oldpl)
  303. {
  304.  struct PathList *pl1=oldpl,*pl2=*plc,*pl3=NULL;
  305.  
  306.  while (pl1) {
  307.   /* Get memory for path list entry */
  308.   if (!(pl3 || (pl3=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR))))
  309.    return(FALSE); /* No more memory... */
  310.  
  311.   /* Copy path entry */
  312.   if (pl3->PathLock=DupLock(pl1->PathLock)) {
  313.    /* Copy successful, append new entry to list. Head of list? */
  314.    if (*pla)
  315.     pl2->NextPath=MKBADDR(pl3); /* No, append it to list */
  316.    else
  317.     *pla=pl3;                   /* Yes, set list anchor */
  318.  
  319.    /* Save pointer */
  320.    pl2=pl3;
  321.  
  322.    /* Invalidate pointer, next time a new PathList will be allocated */
  323.    pl3=NULL;
  324.   }
  325.  
  326.   /* Get next path list entry */
  327.   pl1=BADDR(pl1->NextPath);
  328.  }
  329.  
  330.  /* Free memory */
  331.  if (pl3) FreeVec(pl3);
  332.  
  333.  /* All OK */
  334.  *plc=pl2; /* Save pointer to new end of list */
  335.  return(TRUE);
  336. }
  337.  
  338. /* Free a path list */
  339. void FreePathList(struct PathList *pla)
  340. {
  341.  /* Check for NULL */
  342.  if (pla) {
  343.   struct PathList *pl1=pla,*pl2;
  344.  
  345.   /* Scan list */
  346.   do {
  347.    /* Get pointer to next entry */
  348.    pl2=BADDR(pl1->NextPath);
  349.  
  350.    /* Free entry */
  351.    UnLock(pl1->PathLock);
  352.    FreeVec(pl1);
  353.   } while (pl1=pl2);
  354.  }
  355. }
  356.  
  357. /* Build a path list from a string */
  358. static BOOL BuildPathList(struct PathList **pla, struct PathList **plc, char *s)
  359. {
  360.  struct FileInfoBlock *fib;
  361.  char *cp1,*cp2=s;
  362.  struct PathList *pl1=*plc,*pl2=NULL;
  363.  
  364.  /* Get memory for FIB */
  365.  if (!(fib=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)))
  366.   return(FALSE);
  367.  
  368.  /* For every path part */
  369.  while (cp1=cp2) {
  370.   /* Search next path part */
  371.   if (cp2=strchr(cp1,',')) *cp2='\0'; /* Add string end character */
  372.  
  373.   /* Get memory for path list entry */
  374.   if (!(pl2 ||
  375.        (pl2=AllocVec(sizeof(struct PathList),MEMF_PUBLIC|MEMF_CLEAR)))) {
  376.    FreeVec(fib);
  377.    return(FALSE); /* No more memory */
  378.   }
  379.  
  380.   /* Get lock */
  381.   if (pl2->PathLock=Lock(cp1,SHARED_LOCK))
  382.    /* Is it a directory? */
  383.    if (Examine(pl2->PathLock,fib) && (fib->fib_DirEntryType>0)) {
  384.     /* Yes, it is a directory, append it to the list. Head of list? */
  385.     if (*pla)
  386.      pl1->NextPath=MKBADDR(pl2); /* No, append it to list */
  387.     else
  388.      *pla=pl2;                   /* Yes, set list anchor */
  389.  
  390.     /* Save pointer */
  391.     pl1=pl2;
  392.  
  393.     /* Invalidate pointer, next time a new PathList will be allocated */
  394.     pl2=NULL;
  395.    }
  396.    else UnLock(pl2->PathLock); /* No, it is a file */
  397.  
  398.   /* Restore string and move to next character */
  399.   if (cp2) *cp2++=',';
  400.  }
  401.  
  402.  *plc=pl1;              /* Save end of list */
  403.  if (pl2) FreeVec(pl2); /* Last Lock() failed, free memory */
  404.  FreeVec(fib);
  405.  
  406.  /* All OK. */
  407.  return(TRUE);
  408. }
  409.  
  410. #define NAMELEN    256  /* Buffer length for a file name */
  411. #define CMDLINELEN 4096 /* Buffer length for command line */
  412.  
  413. /* Build a CLI or ARexx command line (supports [] argument substitution) */
  414. static ULONG BuildCommandLine(char *buf, char *command, BPTR curdir,
  415.                               struct AppMessage *msg)
  416. {
  417.  ULONG cmdlen;      /* Command line length */
  418.  char *lp=command;  /* Pointer to current cmdline pos. */
  419.  char *contp=NULL;  /* Pointer AFTER [] place holder */
  420.  
  421.  /* Search for [] parameter place holder */
  422.  while (lp=strchr(lp,'['))
  423.   /* Place holder found? */
  424.   if (*(lp+1) == ']')
  425.    /* Yes, leave loop */
  426.    break;
  427.   else
  428.    /* No, skip to next one */
  429.    lp++;
  430.  
  431.  /* Copy command name to command line */
  432.  if (lp) {
  433.   /* [] parameter place holder found, copy first part of command */
  434.   cmdlen=lp-command;
  435.   strncpy(buf,command,cmdlen);
  436.   buf[cmdlen]='\0';
  437.   contp=lp+2;
  438.  }
  439.  else {
  440.   strcpy(buf,command); /* No [] parameter place holder */
  441.   cmdlen=strlen(buf);
  442.  }
  443.  lp=buf+cmdlen;
  444.  
  445.  /* Check for arguments */
  446.  if (msg) {
  447.   char *dir; /* Buffer for file names */
  448.  
  449.   /* Get memory for file names */
  450.   if (dir=AllocMem(NAMELEN,MEMF_PUBLIC)) {
  451.    struct WBArg *wa=msg->am_ArgList;  /* Pointer to WBArgs */
  452.    int i;                             /* Counter for WBArgs */
  453.  
  454.    for (i=msg->am_NumArgs; i; i--,wa++) {
  455.     char *name,*space;
  456.     ULONG namelen;
  457.  
  458.     /* Skip args which don't support locks! */
  459.     if (!wa->wa_Lock) continue;
  460.  
  461.     /* Append a space for each parameter */
  462.     if (cmdlen>CMDLINELEN-2) break;
  463.     *lp++=' ';
  464.     cmdlen++;
  465.  
  466.     /* Build parameter from Lock & name */
  467.     DEBUG_PRINTF("wa_Name: 0x%08lx\n",wa->wa_Name);
  468.     DEBUG_PRINTF("wa_Name: '%s'\n",wa->wa_Name);
  469.     if (*(wa->wa_Name)!='\0')
  470.      /* File name --> build complete path name */
  471.      if (SameLock(curdir,wa->wa_Lock)==LOCK_SAME)
  472.       /* File in current directory -> "<file>" */
  473.       name=(char *) wa->wa_Name;
  474.      else {
  475.       /* File in other directory -> "<path><seperator><file>" */
  476.       if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue;
  477.       if (!AddPart(dir,wa->wa_Name,NAMELEN)) continue;
  478.       name=dir;
  479.      }
  480.     else {
  481.      /* No file name --> Drawer */
  482.      if (!NameFromLock(wa->wa_Lock,dir,NAMELEN)) continue;
  483.      name=dir;
  484.     }
  485.     namelen=strlen(name);
  486.  
  487.     /* Handle special case: Space in a filename */
  488.     if (space=strchr(name,' ')) namelen+=2;
  489.  
  490.     /* Does parameter fit into commandline? */
  491.     if (cmdlen+namelen>CMDLINELEN-2) break;
  492.  
  493.     if (space) *lp++='"';   /* Quote file name (beginning) */
  494.     strcpy(lp,name);        /* Append parameter */
  495.     lp+=namelen;            /* Correct pointer */
  496.     if (space) {
  497.      lp--;                  /* Correct pointer */
  498.      *(lp-1)='"';           /* Quote file name (end) */
  499.     }
  500.     cmdlen+=namelen;        /* New command line length */
  501.  
  502.     DEBUG_PRINTF("Parameter: '%s'\n",buf);
  503.    }
  504.    FreeMem(dir,NAMELEN);
  505.   }
  506.  }
  507.  
  508.  /* Check for [] parameter place holder, Find closing bracket */
  509.  if (contp && (cmdlen+strlen(contp)<CMDLINELEN-1)) {
  510.   strcpy(lp,contp); /* Copy second part of command */
  511.   lp=lp+strlen(lp); /* Move to end of string */
  512.  }
  513.  else
  514.   *lp='\0';       /* Set string terminator */
  515.  
  516.  /* Return command line length */
  517.  return(lp-buf);
  518. }
  519.  
  520. /* Start CLI program */
  521. static BOOL StartCLIProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  522. {
  523.  char *cmd;     /* Buffer for command line */
  524.  BOOL rc=FALSE;
  525.  
  526.  /* Get memory for command line */
  527.  if (cmd=AllocMem(CMDLINELEN,MEMF_PUBLIC)) {
  528.   BPTR newcd; /* Lock for program's current directory */
  529.  
  530.   if (newcd=Lock(tmobj->eo_CurrentDir,SHARED_LOCK)) {
  531.    BPTR ofh; /* AmigaDOS file handle (output) */
  532.  
  533.    /* Build command line */
  534.    BuildCommandLine(cmd,tmobj->eo_Command,newcd,msg);
  535.  
  536.    /* Open output file */
  537.    if (ofh=Open(tmobj->eo_Output,MODE_NEWFILE)) {
  538.     BPTR ifh; /* AmigaDOS file handle (input) */
  539.     struct MsgPort *newct=NULL;          /* New ConsoleTask pointer */
  540.  
  541.     /* Is the output file an interactive file? */
  542.     if (IsInteractive(ofh)) {
  543.      struct MsgPort *oldct;  /* Old ConsoleTask pointer */
  544.  
  545.      /* Yes. We need the same file as input file for CTRL-C/D/E/F redirection */
  546.      /* Set our ConsoleTask to the new output file, so that we can re-open it */
  547.      newct=((struct FileHandle *) BADDR(ofh))->fh_Type;
  548.      oldct=SetConsoleTask(newct);
  549.  
  550.      /* Open the new input file (Now ifh points to the same file as ofh) */
  551.      ifh=Open("CONSOLE:",MODE_OLDFILE);
  552.  
  553.      /* Change back to old ConsoleTask */
  554.      SetConsoleTask(oldct);
  555.     }
  556.     /* Non-interactive output, open dummy input file */
  557.     else ifh=Open(DefaultOutput,MODE_OLDFILE);
  558.  
  559.     if (ifh) {
  560.      struct PathList *pla=NULL,*plc=NULL;
  561.  
  562.      /* Build path list, local path first, then global path*/
  563.      if (BuildPathList(&pla,&plc,tmobj->eo_Path) &&
  564.          CopyPathList(&pla,&plc,GlobalPath)) {
  565.       BPTR oldcd; /* pointer to old current directory */
  566.  
  567.       /* Go to program's current directory */
  568.       oldcd=CurrentDir(newcd);
  569.  
  570.       /* Start program */
  571.       if (SystemTags(cmd,SYS_Output,     ofh,
  572.                          SYS_Input,      ifh,
  573.                          SYS_Asynch,     TRUE, /* Run program asynchron */
  574.                          SYS_UserShell,  TRUE, /* Use user specified shell */
  575.                          NP_StackSize,   tmobj->eo_Stack,
  576.                          NP_Priority,    tmobj->eo_Priority,
  577.                          NP_Path,        MKBADDR(pla),
  578.                          NP_ConsoleTask, newct,
  579.                          TAG_DONE)!=-1)
  580.        rc=TRUE; /* Program started! */
  581.  
  582.       /* Go back to old current directory */
  583.       CurrentDir(oldcd);
  584.      }
  585.      if (!rc) FreePathList(pla); /* Free path list if program wasn't started */
  586.      if (!rc) Close(ifh); /* Close input file if program wasn't started */
  587.     }
  588.     if (!rc) Close(ofh); /* Close output file if program wasn't started */
  589.    }
  590.    UnLock(newcd);
  591.   }
  592.   FreeMem(cmd,CMDLINELEN);
  593.  }
  594.  return(rc);
  595. }
  596.  
  597. /* Start WB program */
  598. static BOOL StartWBProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  599. {
  600.  BOOL rc                     = FALSE;
  601.  
  602.  /* Open wbstart.library */
  603.  if (WBStartBase = OpenLibrary(WBSTART_NAME, WBSTART_VERSION)) {
  604.  
  605.   /* Start WB program */
  606.   rc = WBStartTags(WBStart_Name,          tmobj->eo_Command,
  607.                    WBStart_DirectoryName, tmobj->eo_CurrentDir,
  608.                    WBStart_Stack,         tmobj->eo_Stack,
  609.                    WBStart_Priority,      tmobj->eo_Priority,
  610.                    WBStart_ArgumentCount, msg ? msg->am_NumArgs : 0,
  611.                    WBStart_ArgumentList,  msg ? msg->am_ArgList : 0,
  612.                    TAG_DONE)
  613.         == RETURN_OK;
  614.  
  615.   /* Close library */
  616.   CloseLibrary(WBStartBase);
  617.  }
  618.  
  619.  return(rc);
  620. }
  621.  
  622. /* Start ARexx program */
  623. static BOOL StartARexxProgram(struct TMObjectExec *tmobj,
  624.                               struct AppMessage *msg)
  625. {
  626.  char *cmd;     /* Buffer for command line */
  627.  BOOL rc=FALSE;
  628.  
  629.  /* Get memory for command line */
  630.  if (cmd=AllocMem(CMDLINELEN,MEMF_PUBLIC)) {
  631.   BPTR newcd; /* Lock for program's current directory */
  632.  
  633.   if (newcd=Lock(tmobj->eo_CurrentDir,SHARED_LOCK)) {
  634.    ULONG cmdlen; /* Command line length */
  635.    BPTR oldcd;   /* Lock for old current directory */
  636.  
  637.    /* Build command line */
  638.    cmdlen=BuildCommandLine(cmd,tmobj->eo_Command,newcd,msg);
  639.  
  640.    /* Go to program's current directory */
  641.    oldcd=CurrentDir(newcd);
  642.  
  643.    /* Send ARexx command */
  644.    rc=SendARexxCommand(cmd,cmdlen);
  645.  
  646.    /* Go back to old current directory */
  647.    CurrentDir(oldcd);
  648.    UnLock(newcd);
  649.   }
  650.   FreeMem(cmd,CMDLINELEN);
  651.  }
  652.  return(rc);
  653. }
  654.  
  655. /* Start Network program */
  656. static BOOL StartNetworkProgram(struct TMObjectExec *tmobj)
  657. {
  658.  BOOL rc=FALSE;
  659.  
  660.  /* Network installed? */
  661.  if (LocalEntity) {
  662.   char *cmd=tmobj->eo_Command;
  663.   char *hostname;
  664.  
  665.   /* Search '@' seperator */
  666.   if (hostname=strchr(cmd,'@')) {
  667.    /* Host name found */
  668.    ULONG cmdlen=hostname-cmd+1;
  669.    struct Entity *RemoteEntity;
  670.  
  671.    /* Increment pointer */
  672.    hostname++;
  673.  
  674.    DEBUG_PRINTF("Host name: '%s'\n",hostname);
  675.  
  676.    /* Find entity "ToolManager" on remote machine */
  677.    if (RemoteEntity=FindEntity(hostname,ToolManagerName,LocalEntity,NULL)) {
  678.     struct Transaction *trans;
  679.  
  680.     DEBUG_PRINTF("Remote entity: 0x%08lx\n",RemoteEntity);
  681.  
  682.     /* Allocate transaction */
  683.     if (trans=AllocTransaction(TRN_AllocReqBuffer, cmdlen,
  684.                                TAG_DONE)) {
  685.      char *buffer=trans->trans_RequestData;
  686.  
  687.      DEBUG_PRINTF("Transaction: 0x%08lx\n",trans);
  688.  
  689.      /* Init transaction */
  690.      strncpy(buffer,cmd,cmdlen-1);
  691.      buffer[cmdlen-1]='\0';
  692.      trans->trans_ReqDataActual=cmdlen;
  693.      trans->trans_Timeout=10; /* 10 secs timeout for remote machine */
  694.  
  695.      DEBUG_PRINTF("Remote command: '%s'\n",buffer);
  696.  
  697.      /* Do transaction */
  698.      DoTransaction(RemoteEntity,LocalEntity,trans);
  699.      rc=(trans->trans_Error == ENVOYERR_NOERROR);
  700.  
  701.      DEBUG_PRINTF("Network error: %ld\n",trans->trans_Error);
  702.  
  703.      /* Free transaction */
  704.      FreeTransaction(trans);
  705.     }
  706.  
  707.     /* Release remote entity */
  708.     LoseEntity(RemoteEntity);
  709.    }
  710.   }
  711.  }
  712.  return(rc);
  713. }
  714.  
  715. /* Input desctription structure for ParseIX() */
  716. static struct InputXpression ParseBuffer={IX_VERSION};
  717.  
  718. void kprintf(char *, ...);
  719.  
  720. /* Create an input event from a Commodities description string */
  721. static struct InputEvent *CreateInputEvent(struct TMObjectExec *tmobj)
  722. {
  723.  struct InputEvent *ie;
  724.  
  725.  /* Allocate memory for input event */
  726.  if (ie=AllocMem(sizeof(struct InputEvent),MEMF_CLEAR|MEMF_PUBLIC)) {
  727.  
  728.   /* Parse description string */
  729.   if (!ParseIX(tmobj->eo_Command,&ParseBuffer)) {
  730.  
  731.    /* Description OK, initialize input event */
  732.    ie->ie_Class    =ParseBuffer.ix_Class;
  733.    ie->ie_Code     =ParseBuffer.ix_Code;
  734.    ie->ie_Qualifier=ParseBuffer.ix_Qualifier;
  735.  
  736.    /* All OK */
  737.    return(ie);
  738.   }
  739.  
  740.   /* Error in description string, free input event */
  741.   FreeMem(ie,sizeof(struct InputEvent));
  742.  }
  743.  return(NULL);
  744. }
  745.  
  746. /* Start program */
  747. static void StartProgram(struct TMObjectExec *tmobj, struct AppMessage *msg)
  748. {
  749.  struct AppMessage *args=(tmobj->eo_Flags & EO_Arguments) ? msg : NULL;
  750.  BOOL rc=FALSE;
  751.  
  752.  /* Check for command */
  753.  if (!tmobj->eo_Command) return; /* Nothing to do */
  754.  
  755.  /* Check for ToFront flag */
  756.  if (tmobj->eo_Flags & EO_ToFront) {
  757.   /* Move screen to front */
  758.   struct Screen *s=LockPubScreen(tmobj->eo_PubScreen);
  759.  
  760.   if (s) {
  761.    ScreenToFront(s);
  762.    UnlockPubScreen(NULL,s);
  763.   }
  764.  }
  765.  
  766.  /* Check for program type */
  767.  switch (tmobj->eo_Type) {
  768.   case TMET_CLI:     rc=StartCLIProgram(tmobj,args);
  769.                      break;
  770.   case TMET_WB:      rc=StartWBProgram(tmobj,args);
  771.                      break;
  772.   case TMET_ARexx:   rc=StartARexxProgram(tmobj,args);
  773.                      break;
  774.   case TMET_Dock:    /* Dock already linked or can we create a link? */
  775.                      if (tmobj->eo_LinkData ||
  776.                          (tmobj->eo_LinkData=AddLinkTMObject(tmobj->eo_Handle,
  777.                                                              tmobj->eo_Command,
  778.                                                              TMOBJTYPE_DOCK,
  779.                                                  (struct TMObject *) tmobj))) {
  780.                       /* Yes, activate it */
  781.                       CallActivateTMObject(tmobj->eo_LinkData,NULL);
  782.                       rc=TRUE;
  783.                      }
  784.                      break;
  785.   case TMET_HotKey:  /* Input event already created or can we create it? */
  786.                      if (tmobj->eo_LinkData ||
  787.                          (tmobj->eo_LinkData=CreateInputEvent(tmobj))) {
  788.                       /* Yes */
  789.                       struct InputEvent *ie=tmobj->eo_LinkData;
  790.  
  791.                       /* Set time stamp */
  792.                       CurrentTime(&ie->ie_TimeStamp.tv_secs,
  793.                                   &ie->ie_TimeStamp.tv_micro);
  794.  
  795.                       /* Enqueue event */
  796.                       AddIEvents(tmobj->eo_LinkData);
  797.                       rc=TRUE;
  798.                      }
  799.                      break;
  800.   case TMET_Network: rc=StartNetworkProgram(tmobj); /* No args possible */
  801.                      break;
  802.   case TMET_Hook:    {
  803.                       struct Hook *hook=(struct Hook *) tmobj->eo_Command;
  804.                       HookFuncPtr Entry = (HookFuncPtr) hook->h_Entry;
  805.  
  806.                       /* Call hook function. Calling conventions:          */
  807.                       /* A0 (hook)   : pointer to hook structure           */
  808.                       /* A1 (message): pointer to AppMessage (may be NULL) */
  809.                       /* A2 (object) : value of hook->h_Data               */
  810.                       /* Return Code : BOOL, FALSE for failure             */
  811.                       rc=Entry(hook,args,hook->h_Data);
  812.                      }
  813.                      break;
  814.  }
  815.  
  816.  /* Error? */
  817.  if (!rc) DisplayBeep(NULL);
  818. }
  819.  
  820. /* Send timer request */
  821. static void SendTimerRequest(struct TMObjectExec *tmobj)
  822. {
  823.  struct timerequest *tr=(struct timerequest *) &tmobj->eo_TimerReq;
  824.  
  825.  /* Initialize timer request */
  826.  tr->tr_node.io_Command=TR_ADDREQUEST;
  827.  tr->tr_time.tv_secs=labs(tmobj->eo_Delay);
  828.  tr->tr_time.tv_micro=0;
  829.  
  830.  /* Send timer request */
  831.  SendIO((struct IORequest *) tr);
  832.  tmobj->eo_Link.tml_Active=(void *) TRUE;
  833. }
  834.  
  835. /* Activate an Exec object */
  836. void ActivateTMObjectExec(struct TMLink *tml, struct AppMessage *msg)
  837. {
  838.  struct TMObjectExec *tmobj=(struct TMObjectExec *) tml->tml_Linked;
  839.  
  840.  DEBUG_PRINTF("Activate/Exec (0x%08lx)\n",msg);
  841.  
  842.  /* Is timer active? */
  843.  if (tmobj->eo_Link.tml_Active) {
  844.   /* Yes. a) got timer event, b) user wants to stop last request */
  845.   struct IORequest *tr=(struct IORequest *) &tmobj->eo_TimerReq;
  846.  
  847.   /* Check timer request */
  848.   if (CheckIO(tr)) {
  849.    /* a) Timer event finished, remove it. */
  850.    WaitIO(tr);
  851.    tmobj->eo_Link.tml_Active=FALSE;
  852.  
  853.    /* Start program, no arguments */
  854.    StartProgram(tmobj,NULL);
  855.  
  856.    /* repeat event? */
  857.    if (tmobj->eo_Delay<0) SendTimerRequest(tmobj);
  858.   }
  859.   else {
  860.    /* b) user wants to stop last request, abort it */
  861.    AbortIO(tr);
  862.    WaitIO(tr);
  863.    tmobj->eo_Link.tml_Active=FALSE;
  864.   }
  865.  }
  866.  /* Timer not active, start program or time request */
  867.  else if (tmobj->eo_Delay!=0) SendTimerRequest(tmobj);
  868.  
  869.  /* Start program */
  870.  else StartProgram(tmobj,msg);
  871. }
  872.